//------------------------------------------------------------------------------
// <copyright file="RpcArchiveImpl.h" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//------------------------------------------------------------------------------

#pragma once

// Disable warnings about XML comments on template functions.
#pragma warning(disable:4634)

#include <map>

namespace Microsoft { namespace Internal { namespace GamesTest { namespace Rpc { namespace Server
{
	class RpcBinaryDataImpl;

	/// <summary> 
	/// An implementation of the RpcArchive class.
	/// </summary>
	class RpcArchiveImpl
	{
	public:
		/// <summary> 
		/// The values for field type meta-data passed to clients.
		/// </summary>
		enum class FieldTypes
		{
			Unknown = 0,
			Archive,
			String,
			Bool,
			Int8,
			UInt8,
			Char,
			UShort,
			Short,
			Int,
			UInt,
			Long,
			ULong,
			Int64,
			UInt64,
			Float,
			Double,
			Blob
		};

		typedef std::map<std::wstring, FieldTypes> FieldTypesMap;

	public:
		/// <summary> 
		/// The underlying JsonObject that contains all archive fields.
		/// </summary>
		mutable JsonNode m_jsonObject;

		/// <summary> 
		/// Records the original types of all archive fields as they are set.
		/// </summary>
		/// <remarks>
		/// Used for lazy update of a hidden element in Archive's JSON structure only when serialization is requested.
		/// We cannot infer the types of archive fields because they are converted to JSON types on the fly, and
		/// there is no 1:1 correlation between source types used in SetNamedValue/Collection and resulting JSON types.
		/// Because of this, we have to record the type information on the fly and store it.
		/// </remarks>
		mutable FieldTypesMap m_fieldTypes;

		/// <summary> 
		/// The Json container serialized as a string so that we can return its internal memory directly.
		/// </summary>
		mutable std::wstring m_serializedData;

	public:
		/// <summary> 
		/// Initializes a new instance of the RpcArchiveImpl class.
		/// </summary>
		RpcArchiveImpl();

		/// <summary> 
		/// Initializes a new instance of the RpcArchiveImpl class. This will create an instance of the RpcArchiveImpl
		/// class based on the given existing implementation object.
		/// </summary>
		/// <param name="other">The existing implementation object to be used by the new RpcArchiveImpl.</param>
		RpcArchiveImpl(const RpcArchiveImpl& other);

		/// <summary>
		/// Initializes a new instance of the RpcArchiveImpl class. This will move an existing RpcArchive
		/// into a newly created RpcArchiveImpl.
		/// </summary>
		/// <param name="other">The existing archive to be moved.</param>
		RpcArchiveImpl(RpcArchiveImpl&& other);

		/// <summary> 
		/// Initializes a new instance of the RpcArchiveImpl class from parsed JSON object.
		/// This performs a deep copy.
		/// </summary>
		/// <param name="jsonObject">An existing JsonObject to use as a foundation for this class.</param>
		RpcArchiveImpl(const JsonNode& jsonObject);

		/// <summary> 
		/// Creates a deep copy of the archive implementation given by the <paramref name="other"/> parameter.
		/// </summary>
		/// <param name="other">The archive from which a deep copy shall be created.</param>
		RpcArchiveImpl& operator=(const RpcArchiveImpl& other);

		/// <summary>
		/// Moves an existing RpcArchiveImpl to an existing RpcArchiveImpl.
		/// </summary>
		/// <param name="other">The existing archive to be moved.</param>
		RpcArchiveImpl& operator=(RpcArchiveImpl&& other);

		/// <summary> 
		/// Indicates whether or not a field with the given name exists within this archive.
		/// </summary>
		/// <param name="fieldName">The name of the field to check for existence.</param>
		/// <returns>True if a field with the given names exists in the archive, otherwise false.</returns>
		bool HasNamedValue(_In_z_ const wchar_t* fieldName) const;

		/// <summary>
		/// Retrieves an RpcArchiveImpl value from the field with the given name.
		/// </summary>
		/// <param name="fieldName">The name of the field to retrieve the value from.</param>
		/// <param name="fieldValue">A pointer to an RpcArchive to hold the value retrieved by this method.</param>
		/// <returns>S_OK if the field was able to be successfully converted to an RpcArchive, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT GetNamedValue(_In_z_ const wchar_t* fieldName, _Out_ RpcArchiveImpl* fieldValue) const;

		/// <summary> 
		/// Sets a field with the given name to the given RpcArchiveImpl value.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <param name="fieldValue">The value of the field to be set.</param>
		/// <returns>S_OK if the field was able to be set successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT SetNamedValue(_In_z_ const wchar_t* fieldName, RpcArchiveImpl& fieldValue);

		/// <summary> 
		/// Retrieves a boolean value from the field with the given name.
		/// </summary>
		/// <param name="fieldName">The name of the field to retrieve the value from.</param>
		/// <returns>S_OK if the field was able to be successfully converted to a boolean, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT GetNamedValue(_In_z_ const wchar_t* fieldName, _Out_ bool* fieldValue) const;

		/// <summary> 
		/// Sets a field with the given name to the given boolean value.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <returns>S_OK if the field was able to be set successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT SetNamedValue(_In_z_ const wchar_t* fieldName, bool fieldValue);

		/// <summary> 
		/// Retrieves an unsigned 8 bit int value from the field with the given name.
		/// </summary>
		/// <param name="fieldName">The name of the field to retrieve the value from.</param>
		/// <returns>S_OK if the field was able to be successfully converted to an unsigned 8 bit int, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT GetNamedValue(_In_z_ const wchar_t* fieldName, _Out_ unsigned char* fieldValue) const;

		/// <summary> 
		/// Sets a field with the given name to the given unsigned 8 bit int value.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <returns>S_OK if the field was able to be set successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT SetNamedValue(_In_z_ const wchar_t* fieldName, unsigned char fieldValue);

		/// <summary> 
		/// Retrieves an 8 bit int value from the field with the given name.
		/// </summary>
		/// <param name="fieldName">The name of the field to retrieve the value from.</param>
		/// <returns>S_OK if the field was able to be successfully converted to an 8 bit int, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT GetNamedValue(_In_z_ const wchar_t* fieldName, _Out_ char* fieldValue) const;

		/// <summary> 
		/// Sets a field with the given name to the given 8 bit int value.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <returns>S_OK if the field was able to be set successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT SetNamedValue(_In_z_ const wchar_t* fieldName, char fieldValue);

		/// <summary> 
		/// Retrieves an 8 bit int value from the field with the given name.
		/// </summary>
		/// <param name="fieldName">The name of the field to retrieve the value from.</param>
		/// <returns>S_OK if the field was able to be successfully converted to an 8 bit int, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT GetNamedValue(_In_z_ const wchar_t* fieldName, _Out_ signed char* fieldValue) const;

		/// <summary> 
		/// Sets a field with the given name to the given 8 bit int value.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <returns>S_OK if the field was able to be set successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT SetNamedValue(_In_z_ const wchar_t* fieldName, signed char fieldValue);

		/// <summary> 
		/// Retrieves an unsigned 16 bit int value from the field with the given name.
		/// </summary>
		/// <param name="fieldName">The name of the field to retrieve the value from.</param>
		/// <returns>S_OK if the field was able to be successfully converted to an unsigned 16 bit int, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT GetNamedValue(_In_z_ const wchar_t* fieldName, _Out_ unsigned short* fieldValue) const;

		/// <summary> 
		/// Sets a field with the given name to the given unsigned 16 bit int value.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <returns>S_OK if the field was able to be set successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT SetNamedValue(_In_z_ const wchar_t* fieldName, unsigned short fieldValue);

		/// <summary> 
		/// Retrieves an 16 bit int value from the field with the given name.
		/// </summary>
		/// <param name="fieldName">The name of the field to retrieve the value from.</param>
		/// <returns>S_OK if the field was able to be successfully converted to an 16 bit int, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT GetNamedValue(_In_z_ const wchar_t* fieldName, _Out_ short* fieldValue) const;

		/// <summary> 
		/// Sets a field with the given name to the given 16 bit int value.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <returns>S_OK if the field was able to be set successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT SetNamedValue(_In_z_ const wchar_t* fieldName, short fieldValue);

		/// <summary> 
		/// Retrieves an 32 bit int value from the field with the given name.
		/// </summary>
		/// <param name="fieldName">The name of the field to retrieve the value from.</param>
		/// <returns>S_OK if the field was able to be successfully converted to an 32 bit int, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT GetNamedValue(_In_z_ const wchar_t* fieldName, _Out_ int* fieldValue) const;

		/// <summary> 
		/// Sets a field with the given name to the given 32 bit int value.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <returns>S_OK if the field was able to be set successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT SetNamedValue(_In_z_ const wchar_t* fieldName, int fieldValue);

		/// <summary> 
		/// Retrieves an unsigned 32 bit int value from the field with the given name.
		/// </summary>
		/// <param name="fieldName">The name of the field to retrieve the value from.</param>
		/// <returns>S_OK if the field was able to be successfully converted to an unsigned 32 bit int, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT GetNamedValue(_In_z_ const wchar_t* fieldName, _Out_ unsigned int* fieldValue) const;

		/// <summary> 
		/// Sets a field with the given name to the given unsigned 32 bit int value.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <returns>S_OK if the field was able to be set successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT SetNamedValue(_In_z_ const wchar_t* fieldName, unsigned int fieldValue);

		/// <summary> 
		/// Retrieves an 32 bit int value from the field with the given name.
		/// </summary>
		/// <param name="fieldName">The name of the field to retrieve the value from.</param>
		/// <returns>S_OK if the field was able to be successfully converted to an 32 bit int, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT GetNamedValue(_In_z_ const wchar_t* fieldName, _Out_ long* fieldValue) const;

		/// <summary> 
		/// Sets a field with the given name to the given 32 bit int value.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <returns>S_OK if the field was able to be set successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT SetNamedValue(_In_z_ const wchar_t* fieldName, long fieldValue);

		/// <summary> 
		/// Retrieves an unsigned 32 bit int value from the field with the given name.
		/// </summary>
		/// <param name="fieldName">The name of the field to retrieve the value from.</param>
		/// <returns>S_OK if the field was able to be successfully converted to an unsigned 32 bit int, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT GetNamedValue(_In_z_ const wchar_t* fieldName, _Out_ unsigned long* fieldValue) const;

		/// <summary> 
		/// Sets a field with the given name to the given unsigned 32 bit int value.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <returns>S_OK if the field was able to be set successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT SetNamedValue(_In_z_ const wchar_t* fieldName, unsigned long fieldValue);

		/// <summary> 
		/// Retrieves an 64 bit int value from the field with the given name.
		/// </summary>
		/// <param name="fieldName">The name of the field to retrieve the value from.</param>
		/// <returns>S_OK if the field was able to be successfully converted to an 64 bit int, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT GetNamedValue(_In_z_ const wchar_t* fieldName, _Out_ long long* fieldValue) const;

		/// <summary> 
		/// Sets a field with the given name to the given 64 bit int value.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <returns>S_OK if the field was able to be set successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT SetNamedValue(_In_z_ const wchar_t* fieldName, long long fieldValue);

		/// <summary> 
		/// Retrieves an unsigned 64 bit int value from the field with the given name.
		/// </summary>
		/// <param name="fieldName">The name of the field to retrieve the value from.</param>
		/// <returns>S_OK if the field was able to be successfully converted to an unsigned 64 bit int, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT GetNamedValue(_In_z_ const wchar_t* fieldName, _Out_ unsigned long long* fieldValue) const;

		/// <summary> 
		/// Sets a field with the given name to the given unsigned 64 bit int value.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <returns>S_OK if the field was able to be set successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT SetNamedValue(_In_z_ const wchar_t* fieldName, unsigned long long fieldValue);

		/// <summary> 
		/// Retrieves a float value from the field with the given name.
		/// </summary>
		/// <param name="fieldName">The name of the field to retrieve the value from.</param>
		/// <returns>S_OK if the field was able to be successfully converted to a float, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT GetNamedValue(_In_z_ const wchar_t* fieldName, _Out_ float* fieldValue) const;

		/// <summary> 
		/// Sets a field with the given name to the given float value.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <returns>S_OK if the field was able to be set successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT SetNamedValue(_In_z_ const wchar_t* fieldName, float fieldValue);

		/// <summary> 
		/// Retrieves a double value from the field with the given name.
		/// </summary>
		/// <param name="fieldName">The name of the field to retrieve the value from.</param>
		/// <returns>S_OK if the field was able to be successfully converted to a double, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT GetNamedValue(_In_z_ const wchar_t* fieldName, _Out_ double* fieldValue) const;

		/// <summary> 
		/// Sets a field with the given name to the given double value.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <returns>S_OK if the field was able to be set successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT SetNamedValue(_In_z_ const wchar_t* fieldName, double fieldValue);

		/// <summary>
		/// Retrieves an RpcBinaryDataImpl value from the field with the given name.
		/// </summary>
		/// <param name="fieldName">The name of the field to retrieve the value from.</param>
		/// <param name="fieldValue">A pointer to an RpcBinaryDataImpl to hold the value retrieved by this method.</param>
		/// <returns>S_OK if the field was able to be successfully converted to an RpcArchive, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT GetNamedValue(_In_z_ const wchar_t* fieldName, _Out_ RpcBinaryDataImpl* fieldValue) const;

		/// <summary> 
		/// Sets a field with the given name to the given RpcBinaryDataImpl value.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <param name="fieldValue">The value of the field to be set.</param>
		/// <returns>S_OK if the field was able to be set successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT SetNamedValue(_In_z_ const wchar_t* fieldName, RpcBinaryDataImpl& fieldValue);

		/// <summary>
		/// Gets the length of the string field with the given name.  The length includes the null termination character.
		/// </summary>
		/// <param name="fieldName">The name of the field that contains the string to be measured.</param>
		/// <param name="stringLength">A pointer to a unsigned long that will contain the number of characters in the string indicated by the <paramref name="fieldName"/> parameter.</param>
		/// <returns>S_OK if the field was located and its length was able to be measured, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT MeasureNamedStringValue(_In_z_ const wchar_t* fieldName, _Out_ unsigned long* stringLength) const;

		/// <summary>
		/// Retrieves a string value from the field with the given name.
		/// </summary>
		/// <param name="fieldName">The name of the field to retrieve the value from.</param>
		/// <param name="buffer">A pointer to a user-allocated array of wchar_t where the string value will be written.</param>
		/// <param name="bufferLength">The length of the array given in the <paramref name="buffer"/> parameter.</param>
		/// <param name="charactersWritten">Optional.  Output variable that will contain the number of wchar_t characters written to the buffer pointed to by the <paramref name="buffer"/> parameter,
		/// including the null-termination character.</param>
		/// <returns>S_OK if the string value was able to retrieved successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT GetNamedStringValue(_In_z_ const wchar_t* fieldName, _Out_writes_z_(bufferLength) wchar_t* buffer, _In_  unsigned long bufferLength, _Out_opt_ unsigned long* charactersWritten) const;

		/// <summary> 
		/// Sets a field with the given name to the given string value.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <param name="fieldValue">A pointer to a null-terminated string to store in the RpcArchive.</param>
		/// <returns>S_OK if the field was able to be set successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD
			HRESULT SetNamedStringValue(_In_z_ const wchar_t* fieldName, _In_z_ const wchar_t* fieldValue);

		/// <summary>
		/// Gets the number of elements in the field with given name.
		/// </summary>
		/// <param name="fieldName">The name of the field that represents the collection whose length is to be retrieved.</param>
		/// <param name="numElements">A pointer to a unsigned long that will contain the number of elements in the collection indicated by the <paramref name="fieldName"/> parameter.</param>
		/// <returns>S_OK if the number of elements in the collection was able to retrieved successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT MeasureNamedCollection(_In_z_ const wchar_t* fieldName, _Out_ unsigned long* numElements) const;

		/// <summary>
		/// Gets the contents of the item located at the index given by the <paramref name="elementIndex"/> parameter within the collection in the field with the name given by the <paramref name="fieldName"/> parameter.
		/// </summary>
		/// <param name="fieldName">The name of the field that represents the collection whose content is to be retrieved.</param>
		/// <param name="elementIndex">The index of the element to be retrieved from the collection.</param>
		/// <param name="collectionItem">A pointer to an RpcArchiveImpl where the retrieved element will be stored.</param>
		/// <returns>S_OK if the item was able to retrieved successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT GetNamedCollectionItem(_In_z_ const wchar_t* fieldName, _In_ unsigned long elementIndex, _Out_ RpcArchiveImpl* collectionItem);

		/// <summary>
		/// Gets the contents of the item located at the index given by the <paramref name="elementIndex"/> parameter within the collection in the field with the name given by the <paramref name="fieldName"/> parameter.
		/// </summary>
		/// <param name="fieldName">The name of the field that represents the collection whose content is to be retrieved.</param>
		/// <param name="elementIndex">The index of the element to be retrieved from the collection.</param>
		/// <param name="collectionItem">A pointer to an RpcBinaryDataImpl where the retrieved element will be stored.</param>
		/// <returns>S_OK if the item was able to retrieved successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT GetNamedCollectionItem(_In_z_ const wchar_t* fieldName, _In_ unsigned long elementIndex, _Out_ RpcBinaryDataImpl* collectionItem);

		/// <summary>
		/// Gets the contents of the collection in the field with given name.
		/// </summary>
		/// <param name="fieldName">The name of the field that represents the collection whose content is to be retrieved.</param>
		/// <param name="collectionBuffer">A pointer to an array of bool's that will be used to hold the content of collection referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to retrieved successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT GetNamedCollection(_In_z_ const wchar_t* fieldName, _Out_writes_(numElements) bool* collectionBuffer, _In_ unsigned long numElements) const;

		/// <summary>
		/// Gets the contents of the collection in the field with given name.
		/// </summary>
		/// <param name="fieldName">The name of the field that represents the collection whose content is to be retrieved.</param>
		/// <param name="collectionBuffer">A pointer to an array of signed char's that will be used to hold the content of collection referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to retrieved successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT GetNamedCollection(_In_z_ const wchar_t* fieldName, _Out_writes_(numElements) signed char* collectionBuffer, _In_ unsigned long numElements) const;

		/// <summary>
		/// Gets the contents of the collection in the field with given name.
		/// </summary>
		/// <param name="fieldName">The name of the field that represents the collection whose content is to be retrieved.</param>
		/// <param name="collectionBuffer">A pointer to an array of char's that will be used to hold the content of collection referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to retrieved successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT GetNamedCollection(_In_z_ const wchar_t* fieldName, _Out_writes_(numElements) char* collectionBuffer, _In_ unsigned long numElements) const;

		/// <summary>
		/// Gets the contents of the collection in the field with given name.
		/// </summary>
		/// <param name="fieldName">The name of the field that represents the collection whose content is to be retrieved.</param>
		/// <param name="collectionBuffer">A pointer to an array of unsigned char's that will be used to hold the content of collection referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to retrieved successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT GetNamedCollection(_In_z_ const wchar_t* fieldName, _Out_writes_(numElements) unsigned char* collectionBuffer, _In_ unsigned long numElements) const;

		/// <summary>
		/// Gets the contents of the collection in the field with given name.
		/// </summary>
		/// <param name="fieldName">The name of the field that represents the collection whose content is to be retrieved.</param>
		/// <param name="collectionBuffer">A pointer to an array of short's that will be used to hold the content of collection referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to retrieved successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT GetNamedCollection(_In_z_ const wchar_t* fieldName, _Out_writes_(numElements) short* collectionBuffer, _In_ unsigned long numElements) const;

		/// <summary>
		/// Gets the contents of the collection in the field with given name.
		/// </summary>
		/// <param name="fieldName">The name of the field that represents the collection whose content is to be retrieved.</param>
		/// <param name="collectionBuffer">A pointer to an array of unsigned short's that will be used to hold the content of collection referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to retrieved successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT GetNamedCollection(_In_z_ const wchar_t* fieldName, _Out_writes_(numElements) unsigned short* collectionBuffer, _In_ unsigned long numElements) const;

		/// <summary>
		/// Gets the contents of the collection in the field with given name.
		/// </summary>
		/// <param name="fieldName">The name of the field that represents the collection whose content is to be retrieved.</param>
		/// <param name="collectionBuffer">A pointer to an array of int's that will be used to hold the content of collection referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to retrieved successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT GetNamedCollection(_In_z_ const wchar_t* fieldName, _Out_writes_(numElements) int* collectionBuffer, _In_ unsigned long numElements) const;

		/// <summary>
		/// Gets the contents of the collection in the field with given name.
		/// </summary>
		/// <param name="fieldName">The name of the field that represents the collection whose content is to be retrieved.</param>
		/// <param name="collectionBuffer">A pointer to an array of unsigned int's that will be used to hold the content of collection referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to retrieved successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT GetNamedCollection(_In_z_ const wchar_t* fieldName, _Out_writes_(numElements) unsigned int* collectionBuffer, _In_ unsigned long numElements) const;

		/// <summary>
		/// Gets the contents of the collection in the field with given name.
		/// </summary>
		/// <param name="fieldName">The name of the field that represents the collection whose content is to be retrieved.</param>
		/// <param name="collectionBuffer">A pointer to an array of long's that will be used to hold the content of collection referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to retrieved successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT GetNamedCollection(_In_z_ const wchar_t* fieldName, _Out_writes_(numElements) long* collectionBuffer, _In_ unsigned long numElements) const;

		/// <summary>
		/// Gets the contents of the collection in the field with given name.
		/// </summary>
		/// <param name="fieldName">The name of the field that represents the collection whose content is to be retrieved.</param>
		/// <param name="collectionBuffer">A pointer to an array of unsigned long's that will be used to hold the content of collection referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to retrieved successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT GetNamedCollection(_In_z_ const wchar_t* fieldName, _Out_writes_(numElements) unsigned long* collectionBuffer, _In_ unsigned long numElements) const;

		/// <summary>
		/// Gets the contents of the collection in the field with given name.
		/// </summary>
		/// <param name="fieldName">The name of the field that represents the collection whose content is to be retrieved.</param>
		/// <param name="collectionBuffer">A pointer to an array of long long's that will be used to hold the content of collection referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to retrieved successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT GetNamedCollection(_In_z_ const wchar_t* fieldName, _Out_writes_(numElements) long long* collectionBuffer, _In_ unsigned long numElements) const;

		/// <summary>
		/// Gets the contents of the collection in the field with given name.
		/// </summary>
		/// <param name="fieldName">The name of the field that represents the collection whose content is to be retrieved.</param>
		/// <param name="collectionBuffer">A pointer to an array of unsigned long long's that will be used to hold the content of collection referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to retrieved successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT GetNamedCollection(_In_z_ const wchar_t* fieldName, _Out_writes_(numElements) unsigned long long* collectionBuffer, _In_ unsigned long numElements) const;

		/// <summary>
		/// Gets the contents of the collection in the field with given name.
		/// </summary>
		/// <param name="fieldName">The name of the field that represents the collection whose content is to be retrieved.</param>
		/// <param name="collectionBuffer">A pointer to an array of floats that will be used to hold the content of collection referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to retrieved successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT GetNamedCollection(_In_z_ const wchar_t* fieldName, _Out_writes_(numElements) float* collectionBuffer, _In_ unsigned long numElements) const;

		/// <summary>
		/// Gets the contents of the collection in the field with given name.
		/// </summary>
		/// <param name="fieldName">The name of the field that represents the collection whose content is to be retrieved.</param>
		/// <param name="collectionBuffer">A pointer to an array of doubles that will be used to hold the content of collection referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to retrieved successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT GetNamedCollection(_In_z_ const wchar_t* fieldName, _Out_writes_(numElements) double* collectionBuffer, _In_ unsigned long numElements) const;

		/// <summary>
		/// Gets both the number of strings in the field with given name as well as the total number of characters contained within the collection.
		/// </summary>
		/// <param name="fieldName">The name of the field that represents the string collection whose length is to be retrieved.</param>
		/// <param name="numStrings">A pointer to a unsigned long that will contain the number of strings in the collection indicated by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="totalNumStringCharacters">A pointer to a unsigned long that will contain the total number of all characters in the entire string collection.  This includes space for null-termination characters.</param>
		/// <returns>S_OK if the number of strings in the collection and the total number characters in the collection were able to retrieved successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT MeasureNamedStringCollection(_In_z_ const wchar_t* fieldName, _Out_ unsigned long* numStrings, _Out_ unsigned long* totalNumStringCharacters) const;

		/// <summary>
		/// Gets the contents of the collection in the field with given name.
		/// </summary>
		/// <param name="fieldName">The name of the field that represents the string collection whose content is to be retrieved.</param>
		/// <param name="stringPointers">A pointer to an array of wchar_t pointers that will be used to hold the starting address of each string in the collection referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numStringPointers">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="stringPointers"/> parameter.</param>
		/// <param name="stringPointers">A pointer to an array of wide characters that will be used to hold the entire content of every string in the collection referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numStringCharacters">A unsigned long that indicates the number of wide characters in the array pointed to by the <paramref name="stringContents"/> parameter.</param>
		/// <returns>S_OK if the collection was able to retrieved successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT GetNamedStringCollection(_In_z_ const wchar_t* fieldName, _Out_writes_(numStringPointers) wchar_t** stringPointers, _In_ unsigned long numStringPointers, _Out_writes_(numStringCharacters) wchar_t* stringContents, _In_ unsigned long numStringCharacters) const;

		/// <summary>
		/// Ensures that a collection identified by the <paramref name="collectionFieldName"/> parameter is emptied.  If the collection doesn't exist, an empty collection is created.
		/// If a collection previously existed, it is cleared.
		/// </summary>
		/// <param name="collectionFieldName">The name of the field that contains the collection to clear.</param>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT EnsureNamedCollectionIsEmpty(_In_z_ const wchar_t* collectionFieldName);

		/// <summary>
		/// Adds an RpcArchiveImpl to the collection in the field with the given name.  If the collection does not yet exist it will be created.
		/// </summary>
		/// <param name="fieldName">The name of the field to set to which the element shall be added.  If the collection does not yet exist it will be created.</param>
		/// <param name="elementToBeAdded">The element to be added to the collection.</param>
		/// <returns>S_OK if the element was successfully added to the collection, otherwise an HRESULT representing a failure.</returns>
		/// <remarks>This method is used to decouple RpcArchiveImpl from RpcArchive. All implementations only deal with other implementations.</remarks>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT AddItemToNamedCollection(_In_z_ const wchar_t* collectionFieldName, RpcArchiveImpl* elementToBeAdded);

		/// <summary>
		/// Adds an RpcBinaryDataImpl to the collection in the field with the given name.  If the collection does not yet exist it will be created.
		/// </summary>
		/// <param name="fieldName">The name of the field to set to which the element shall be added.  If the collection does not yet exist it will be created.</param>
		/// <param name="elementToBeAdded">The element to be added to the collection.</param>
		/// <returns>S_OK if the element was successfully added to the collection, otherwise an HRESULT representing a failure.</returns>
		/// <remarks>This method is used to decouple RpcBinaryDataImpl from RpcBinaryData. All implementations only deal with other implementations.</remarks>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT AddItemToNamedCollection(_In_z_ const wchar_t* collectionFieldName, RpcBinaryDataImpl* elementToBeAdded);

		/// <summary>
		/// Sets a field with the given name to the given collection.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <param name="collectionBuffer">A pointer to an array of bool's that will be added to the archive as a collection with the name referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to be added to the archive successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT SetNamedCollection(_In_z_ const wchar_t* fieldName, _In_reads_(numElements) bool* collectionBuffer, _In_ unsigned long numElements);

		/// <summary>
		/// Sets a field with the given name to the given collection.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <param name="collectionBuffer">A pointer to an array of signed char's that will be added to the archive as a collection with the name referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to be added to the archive successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT SetNamedCollection(_In_z_ const wchar_t* fieldName, _In_reads_(numElements) signed char* collectionBuffer, _In_ unsigned long numElements);

		/// <summary>
		/// Sets a field with the given name to the given collection.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <param name="collectionBuffer">A pointer to an array of char's that will be added to the archive as a collection with the name referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to be added to the archive successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT SetNamedCollection(_In_z_ const wchar_t* fieldName, _In_reads_(numElements) char* collectionBuffer, _In_ unsigned long numElements);

		/// <summary>
		/// Sets a field with the given name to the given collection.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <param name="collectionBuffer">A pointer to an array of unsigned char's that will be added to the archive as a collection with the name referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to be added to the archive successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT SetNamedCollection(_In_z_ const wchar_t* fieldName, _In_reads_(numElements) unsigned char* collectionBuffer, _In_ unsigned long numElements);

		/// <summary>
		/// Sets a field with the given name to the given collection.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <param name="collectionBuffer">A pointer to an array of short's that will be added to the archive as a collection with the name referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to be added to the archive successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT SetNamedCollection(_In_z_ const wchar_t* fieldName, _In_reads_(numElements) short* collectionBuffer, _In_ unsigned long numElements);

		/// <summary>
		/// Sets a field with the given name to the given collection.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <param name="collectionBuffer">A pointer to an array of unsigned short's that will be added to the archive as a collection with the name referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to be added to the archive successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT SetNamedCollection(_In_z_ const wchar_t* fieldName, _In_reads_(numElements) unsigned short* collectionBuffer, _In_ unsigned long numElements);

		/// <summary>
		/// Sets a field with the given name to the given collection.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <param name="collectionBuffer">A pointer to an array of int's that will be added to the archive as a collection with the name referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to be added to the archive successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT SetNamedCollection(_In_z_ const wchar_t* fieldName, _In_reads_(numElements) int* collectionBuffer, _In_ unsigned long numElements);

		/// <summary>
		/// Sets a field with the given name to the given collection.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <param name="collectionBuffer">A pointer to an array of unsigned int's that will be added to the archive as a collection with the name referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to be added to the archive successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT SetNamedCollection(_In_z_ const wchar_t* fieldName, _In_reads_(numElements) unsigned int* collectionBuffer, _In_ unsigned long numElements);

		/// <summary>
		/// Sets a field with the given name to the given collection.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <param name="collectionBuffer">A pointer to an array of long's that will be added to the archive as a collection with the name referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to be added to the archive successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT SetNamedCollection(_In_z_ const wchar_t* fieldName, _In_reads_(numElements) long* collectionBuffer, _In_ unsigned long numElements);

		/// <summary>
		/// Sets a field with the given name to the given collection.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <param name="collectionBuffer">A pointer to an array of unsigned long's that will be added to the archive as a collection with the name referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to be added to the archive successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT SetNamedCollection(_In_z_ const wchar_t* fieldName, _In_reads_(numElements) unsigned long* collectionBuffer, _In_ unsigned long numElements);

		/// <summary>
		/// Sets a field with the given name to the given collection.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <param name="collectionBuffer">A pointer to an array of long long's that will be added to the archive as a collection with the name referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to be added to the archive successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT SetNamedCollection(_In_z_ const wchar_t* fieldName, _In_reads_(numElements) long long* collectionBuffer, _In_ unsigned long numElements);

		/// <summary>
		/// Sets a field with the given name to the given collection.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <param name="collectionBuffer">A pointer to an array of unsigned long long's that will be added to the archive as a collection with the name referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to be added to the archive successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT SetNamedCollection(_In_z_ const wchar_t* fieldName, _In_reads_(numElements) unsigned long long* collectionBuffer, _In_ unsigned long numElements);

		/// <summary>
		/// Sets a field with the given name to the given collection.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <param name="collectionBuffer">A pointer to an array of floats that will be added to the archive as a collection with the name referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to be added to the archive successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT SetNamedCollection(_In_z_ const wchar_t* fieldName, _In_reads_(numElements) float* collectionBuffer, _In_ unsigned long numElements);

		/// <summary>
		/// Sets a field with the given name to the given collection.
		/// </summary>
		/// <param name="fieldName">The name of the field to set.</param>
		/// <param name="collectionBuffer">A pointer to an array of doubles that will be added to the archive as a collection with the name referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numElements">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="collectionBuffer"/> parameter.</param>
		/// <returns>S_OK if the collection was able to be added to the archive successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT SetNamedCollection(_In_z_ const wchar_t* fieldName, _In_reads_(numElements) double* collectionBuffer, _In_ unsigned long numElements);

		/// <summary>
		/// Sets a field with the given name to the given collection.
		/// </summary>
		/// <param name="fieldName">The name of the field to be set.</param>
		/// <param name="stringPointers">A pointer to an array of wchar_t pointers that holds the starting address of each string in the collection referred to by the <paramref name="fieldName"/> parameter.</param>
		/// <param name="numStrings">A unsigned long that indicates the total number of elements in the array pointed to by the <paramref name="stringPointers"/> parameter.</param>
		/// <returns>S_OK if the collection was able to be added to the archive successfully, otherwise an HRESULT representing a failure.</returns>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT SetNamedStringCollection(_In_z_ const wchar_t* fieldName, _In_reads_(numStrings) const wchar_t* const* stringPointers, _In_ unsigned long numStrings);

		/// <summary> 
		/// Gets the archive JSON model representation.
		/// </summary>
		/// <returns>Archive contents as JSON model.</returns>
		const JsonNode& GetJson() const;

		/// <summary>
		/// Gets a type of the field specified by fieldName (useful for unit tests and external interface).
		/// </summary>
		/// <param name="fieldName">The name of the field.</param>
		FieldTypes GetNamedValueType(_In_z_ const wchar_t* fieldName);

		/// <summary>
		/// Gets a value indicating whether a given field is a collection (useful for unit tests and external interface).
		/// </summary>
		/// <param name="fieldName">The name of the field.</param>
		bool IsNamedCollection(_In_z_ const wchar_t* fieldName);

		/// <summary> 
		/// Clears all fields in this object.  Useful because implementation objects
		/// are pooled and re-used.
		/// </summary>
		void Clear();

		/// <summary>
		/// Deserializes from Json.
		/// </summary>
		/// <param name="json">Json object to deserialize from.</param>
		void Deserialize(const JsonNode& json);

		virtual ~RpcArchiveImpl();

	private:
		/// <summary> 
		/// Creates a hidden meta-data element that allows JsonContractSerializer to parse the Archive object in C# client.
		/// </summary>
		/// <remarks>
		/// Also creates a placeholder for a hidden array used to contain meta-data for each named value.
		/// This array is not filled in with valid information from m_fieldTypes until the moment that the archive is serialized.
		/// </remarks>
		void AddTypeMetadataIfMissing();

		/// <summary> 
		/// Serializes continuously recorded meta-data for each field stored in m_fieldTypes map.
		/// into the hidden array at the root of Archive's JSON structure.
		/// </summary>
		/// <remarks>
		/// This is done lazily just before the continuously maintained JSON object for the entire archive is serialized to string.
		/// </remarks>
		void SerializeTypeMetadata();

		/// <summary> 
		/// Parses the serialized meta-data about each named field into the continuously maintained m_fieldTypes map.
		/// </summary>
		void ParseTypeMetadata();

		/// <summary> 
		/// Gets a numeric field value as double, automatically converting to specified type.
		/// </summary>
		template<typename T>
		GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT GetNumericField(_In_z_ const wchar_t* fieldName, _Out_ T* resultValue) const;

		/// <summary> 
		/// Sets a numeric field value, automatically converting from given type to double.
		/// </summary>
		template<typename T>
		void SetNumericField(_In_z_ const wchar_t* fieldName, T numericValue, FieldTypes fieldType);

		/// <summary> 
		/// Gets a numeric collection, automatically converting from double or another numeric type to given type.
		/// </summary>
		template<typename T>
		HRESULT GetNumericCollection(const wchar_t* fieldName, T* destination, unsigned long numElements) const
		{
			HRESULT hr = S_OK;

			VERIFY_PARAM_NOT_NULL(fieldName);
			VERIFY_PARAM_NOT_NULL(destination);

			try
			{
				JsonNode collection = m_jsonObject.GetValue(fieldName);

				if(collection.GetCount() > numElements)
				{
					hr = GAMESTEST_RPC_E_DESTINATION_BUFFER_TOO_SMALL;
					goto end;
				}

				for (unsigned long index = 0; index < collection.GetCount(); ++index)
				{
					destination[index] = (T)collection.GetNumericValue(index);
				}
			}
			catch (std::out_of_range)
			{
				hr = GAMESTEST_RPC_E_MEMBER_NOT_FOUND_IN_ARCHIVE;
				goto end;
			}

		end:
			return hr;
		}

		/// <summary> 
		/// Sets a numeric collection, automatically converting to given type from original numeric type.
		/// </summary>
		template<typename T>
		HRESULT SetNumericCollection(const wchar_t* fieldName, T* source, unsigned long numElements, FieldTypes elementType)
		{
			HRESULT hr = S_OK;

			VERIFY_PARAM_NOT_NULL(fieldName);
			VERIFY_PARAM_NOT_NULL(source);

			try
			{
				JsonNode collection = m_jsonObject.GetArrayValue(fieldName);			

				for(unsigned long index = 0; index < numElements; ++index)
				{
					collection.Add((double)source[index]);
				}

				m_fieldTypes[fieldName] = elementType;
			}
			catch (std::exception)
			{
				hr = E_FAIL;
				goto end;
			}
end:
			return hr;
		}
	};

}}}}}